#include "Poco/Net/EpollClientFactory.h"
#include "Poco/Net/EpollClientSocket.h"
#include "Poco/Net/IPAddress.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/EpollDispatcher.h"
#include "Poco/Net/EpollServer.h"
#include "Poco/Net/Socket.h"
#include "Poco/Exception.h"
#include "Poco/ThreadPool.h"
#include "Poco/Timespan.h"
#include "Poco/Thread.h"
#include <iostream>


using Poco::Net::EpollServer;
using Poco::Net::EpollClientFactory;
using Poco::Net::EpollClientSocket;
using Poco::Net::EpollDispatcher;
using Poco::Net::Socket;
using Poco::ThreadPool;
using Poco::Net::IPAddress;
using Poco::Net::SocketAddress;
using Poco::Thread;

class EchoClientSocket: public EpollClientSocket
{
public:
	EchoClientSocket(int fd): m_fd(fd)
	{
	}
	
	virtual void run()
	{
		/// 多次收发
		Socket socket(m_fd);
		try
		{
			Poco::Timespan ts(1,0);
			socket.setRecvTimeout(ts);
			socket.setSendTimeout(ts);
			char buf[32] = {0};
			int len = 0;
			std::cout<<"fd:"<<m_fd<<std::endl;
			/// under EPOLLET mode,the fd is nonblocked 
			while((len = socket.recvBytes(buf,31)) != EAGAIN)
			{
				if (len == 31)
				{
					socket.sendBytes(buf,len);
					Thread::sleep(100);
					continue;
				}
				else
				{
					socket.sendBytes(buf,len);
				}
				Thread::sleep(100);
				break;
			}
		}
		catch(Poco::Exception& e)
		{
			 std::cout<<e.what()<<std::endl;
			 socket.close();
		}
	}
	
private:
	int m_fd;
};


class EchoFactory: public EpollClientFactory
	/// A factory for TimeServerConnection.
{
public:
	EchoFactory ()
	{}
	
	EchoClientSocket* createClientSocket(int fd)
	{
		return new EchoClientSocket(fd);
	}
};

class ServerMonitor:public Poco::Runnable
{
public:
    ServerMonitor(const ThreadPool& pool,const EpollDispatcher& dispatcher,const EpollServer& server):
    m_pool(pool),m_dispatcher(dispatcher),m_server(server)
	{
		
	}
	virtual void run()
	{
		while(m_server.running())
		{
			Thread::sleep(1000);
			std::cout<<"server closingFdSize:"<<m_server.closingFdSize()<<std::endl;
			std::cout<<"dispather queue size:"<<m_dispatcher.queueSize()<<std::endl;
			std::cout<<"pool idle szie:"<<m_pool.available()<<"\tworking size:"<<m_pool.working()<<std::endl;
		}
	}
private:
	const ThreadPool&				m_pool;
	const EpollDispatcher&			m_dispatcher;
	const EpollServer& 				m_server;
};

int main(int argc, char** argv)
{
	// set-up a server socket
	IPAddress	ip("127.0.0.1");
	Poco::UInt16 port = 7000;
	SocketAddress addr(ip,port);
	ThreadPool pool;
	Thread		monitorThread;
	
	EchoFactory* fatory = new EchoFactory();
	EpollDispatcher dispatch(pool,*fatory);
	EpollServer server(addr,dispatch);
	dispatch.setEpollServer(&server);		/// detecting timeout fd needed,not nessary
	ServerMonitor	monitor(pool,dispatch,server);
	monitorThread.start(monitor);
	server.wait();
}
	


	
	
	
	
	
	
	
	
	
	
	
	
